package io.youngledo.usb.task;

import io.youngledo.usb.util.FileUtils;
import javafx.application.Platform;
import javafx.beans.property.*;

import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

/**
 * 进度跟踪器 - 使用Java 21特性
 * 线程安全的进度跟踪实现
 */
public class ProgressTracker {

    private final String taskId;
    private final TaskType taskType;
    private final String description;

    // 使用JavaFX属性以便UI绑定
    private final DoubleProperty progressProperty = new SimpleDoubleProperty(0.0);
    private final StringProperty statusProperty = new SimpleStringProperty("准备中...");
    private final StringProperty speedProperty = new SimpleStringProperty("");
    private final StringProperty etaProperty = new SimpleStringProperty("");

    // 进度数据
    private final AtomicLong totalBytes = new AtomicLong(0);
    private final AtomicLong processedBytes = new AtomicLong(0);
    private final LocalDateTime startTime;
    private volatile LocalDateTime lastUpdateTime;
    private volatile boolean cancelled = false;
    private volatile boolean paused = false;
    private volatile boolean completed = false;

    // 速度计算
    private final AtomicLong lastProcessedBytes = new AtomicLong(0);
    private volatile long lastSpeedUpdateTime = System.currentTimeMillis();

    // UI更新频率控制
    private volatile long lastUIUpdateTime = System.currentTimeMillis();
    private static final long UI_UPDATE_INTERVAL = 200; // 每200毫秒最多更新一次UI

    // 回调函数
    private Consumer<ProgressTracker> onProgressUpdate;
    private Consumer<ProgressTracker> onCompleted;
    private Consumer<String> onError;

    public ProgressTracker(String taskId, TaskType taskType, String description) {
        this.taskId = taskId;
        this.taskType = taskType;
        this.description = description;
        this.startTime = LocalDateTime.now();
        this.lastUpdateTime = LocalDateTime.now();
    }

    /**
     * 设置总字节数
     */
    public void setTotalBytes(long totalBytes) {
        this.totalBytes.set(totalBytes);
        updateProgress();
    }

    /**
     * 更新已处理的字节数
     */
    public void updateProcessedBytes(long processedBytes) {
        this.processedBytes.set(processedBytes);
        this.lastUpdateTime = LocalDateTime.now();
        updateProgress();
    }

    /**
     * 增加已处理的字节数
     */
    public void addProcessedBytes(long deltaBytes) {
        long newProcessed = this.processedBytes.addAndGet(deltaBytes);
        this.lastUpdateTime = LocalDateTime.now();
        updateProgress();
    }

    /**
     * 更新进度显示
     */
    private void updateProgress() {
        if (cancelled || paused || completed) return;

        long currentTime = System.currentTimeMillis();

        // 控制UI更新频率 - 最多每200ms更新一次
        if (currentTime - lastUIUpdateTime < UI_UPDATE_INTERVAL) {
            return;
        }

        lastUIUpdateTime = currentTime;
        long total = totalBytes.get();
        long processed = processedBytes.get();

        Platform.runLater(() -> {
            // 更新进度百分比
            if (total > 0) {
                double progress = (double) processed / total;
                progressProperty.set(Math.min(progress, 1.0));
            }

            // 更新状态文本
            statusProperty.set(formatProgressStatus(processed, total));

            // 计算并更新速度
            updateSpeed();

            // 计算并更新预计完成时间
            updateETA();

            // 触发进度更新回调
            if (onProgressUpdate != null) {
                onProgressUpdate.accept(this);
            }
        });
    }

    /**
     * 更新速度信息
     */
    private void updateSpeed() {
        long currentTime = System.currentTimeMillis();
        long timeDiff = currentTime - lastSpeedUpdateTime;

        if (timeDiff >= 1000) { // 每秒更新一次速度
            long currentProcessed = processedBytes.get();
            long bytesDiff = currentProcessed - lastProcessedBytes.get();

            if (timeDiff > 0) {
                double speedBps = (double) bytesDiff / (timeDiff / 1000.0);
                speedProperty.set(formatSpeed(speedBps));
            }

            lastProcessedBytes.set(currentProcessed);
            lastSpeedUpdateTime = currentTime;
        }
    }

    /**
     * 更新预计完成时间
     */
    private void updateETA() {
        long total = totalBytes.get();
        long processed = processedBytes.get();

        if (total > 0 && processed > 0) {
            long remaining = total - processed;
            if (remaining > 0) {
                // 基于当前速度计算ETA
                String speedText = speedProperty.get();
                if (!speedText.isEmpty() && !speedText.equals("0 B/s")) {
                    try {
                        // 简单的ETA计算，可以进一步优化
                        long elapsedSeconds = java.time.Duration.between(startTime, LocalDateTime.now()).getSeconds();
                        if (elapsedSeconds > 0) {
                            double avgSpeed = (double) processed / elapsedSeconds;
                            if (avgSpeed > 0) {
                                long etaSeconds = (long) (remaining / avgSpeed);
                                etaProperty.set(formatDuration(etaSeconds));
                            }
                        }
                    } catch (Exception e) {
                        etaProperty.set("--:--");
                    }
                } else {
                    etaProperty.set("--:--");
                }
            } else {
                etaProperty.set("00:00");
            }
        }
    }

    /**
     * 格式化进度状态文本
     */
    private String formatProgressStatus(long processed, long total) {
        if (total > 0) {
            return String.format("%s / %s (%.1f%%)",
                FileUtils.formatSize(processed),
                FileUtils.formatSize(total),
                (double) processed / total * 100);
        } else {
            return FileUtils.formatSize(processed);
        }
    }

    /**
     * 格式化速度
     */
    private String formatSpeed(double bytesPerSecond) {
        if (bytesPerSecond < 1024) return String.format("%.0f B/s", bytesPerSecond);
        if (bytesPerSecond < 1024 * 1024) return String.format("%.1f KB/s", bytesPerSecond / 1024);
        if (bytesPerSecond < 1024 * 1024 * 1024) return String.format("%.1f MB/s", bytesPerSecond / (1024 * 1024));
        return String.format("%.1f GB/s", bytesPerSecond / (1024 * 1024 * 1024));
    }

    /**
     * 格式化时间长度
     */
    private String formatDuration(long seconds) {
        if (seconds < 60) {
            return String.format("00:%02d", seconds);
        } else if (seconds < 3600) {
            return String.format("%02d:%02d", seconds / 60, seconds % 60);
        } else {
            return String.format("%02d:%02d:%02d", seconds / 3600, (seconds % 3600) / 60, seconds % 60);
        }
    }

    /**
     * 标记任务完成
     */
    public void complete() {
        if (!cancelled) {
            completed = true; // 设置完成标志
            lastUIUpdateTime = 0; // 强制下次UI更新
            Platform.runLater(() -> {
                progressProperty.set(1.0);
                statusProperty.set("完成");
                speedProperty.set("");
                etaProperty.set("00:00");

                if (onCompleted != null) {
                    onCompleted.accept(this);
                }
            });
        }
    }

    /**
     * 标记任务失败
     */
    public void fail(String errorMessage) {
        completed = true; // 设置完成标志
        lastUIUpdateTime = 0; // 强制下次UI更新
        Platform.runLater(() -> {
            statusProperty.set("失败: " + errorMessage);
            speedProperty.set("");
            etaProperty.set("--:--");

            if (onError != null) {
                onError.accept(errorMessage);
            }
        });
    }

    /**
     * 取消任务
     */
    public void cancel() {
        this.cancelled = true;
        Platform.runLater(() -> {
            statusProperty.set("已取消");
            speedProperty.set("");
            etaProperty.set("--:--");
        });
    }

    /**
     * 暂停任务
     */
    public void pause() {
        this.paused = true;
        Platform.runLater(() -> {
            statusProperty.set("已暂停");
            speedProperty.set("");
        });
    }

    /**
     * 恢复任务
     */
    public void resume() {
        this.paused = false;
        this.lastSpeedUpdateTime = System.currentTimeMillis();
        this.lastProcessedBytes.set(processedBytes.get());
    }

    // Getters and Setters
    public String getTaskId() { return taskId; }
    public TaskType getTaskType() { return taskType; }
    public String getDescription() { return description; }
    public boolean isCancelled() { return cancelled; }
    public boolean isPaused() { return paused; }
    public boolean isCompleted() { return completed; }
    public LocalDateTime getStartTime() { return startTime; }

    // JavaFX Property accessors
    public DoubleProperty progressProperty() { return progressProperty; }
    public StringProperty statusProperty() { return statusProperty; }
    public StringProperty speedProperty() { return speedProperty; }
    public StringProperty etaProperty() { return etaProperty; }

    public double getProgress() { return progressProperty.get(); }
    public String getStatus() { return statusProperty.get(); }
    public String getSpeed() { return speedProperty.get(); }
    public String getEta() { return etaProperty.get(); }
    public long getTotalBytes() { return totalBytes.get(); }
    public long getProcessedBytes() { return processedBytes.get(); }

    // Callback setters
    public void setOnProgressUpdate(Consumer<ProgressTracker> callback) {
        this.onProgressUpdate = callback;
    }

    public void setOnCompleted(Consumer<ProgressTracker> callback) {
        this.onCompleted = callback;
    }

    public void setOnError(Consumer<String> callback) {
        this.onError = callback;
    }
}